# CMakeLists
#
# CMake configuration for generating build system of Open BEAGLE
# Copyright (C) 2009-2012
#
# Christian Gagne <christian.gagne@gel.ulaval.ca>
# Marc-Andre Gardner <marc-andre.gardner.1@ulaval.ca>
# Felix-Antoine Fortin <felix-antoine.fortin.1@ulaval.ca>
# Francois-Michel De Rainville <francois-michel.de-rainville.1@ulaval.ca>
#
# Date: 01/08/2012

# Minimal CMake version
cmake_minimum_required(VERSION 2.6)

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules/")

if(COMMAND cmake_policy)
		   cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)

# Set project variables
project(OpenBEAGLE C CXX)
set(BEAGLE_PACKAGE OpenBEAGLE)
set(BEAGLE_VERSION 4.1.0)
if(APPLE)
	option(BEAGLE_CREATE_DMG "Do you want to create a pkg package for Open BEAGLE?" OFF)
elseif(WIN32)
	option(BEAGLE_CREATE_WIN32_SETUP "Do you want to create a setup program for Open BEAGLE (NSIS needed)?" OFF)
elseif(UNIX)
	option(BEAGLE_CREATE_UNIX_BIN "Do you want to create Unix universal binaries files for Open BEAGLE?" OFF)
	option(BEAGLE_CREATE_DEB "Do you want to create a DEB package for Open BEAGLE?" OFF)
	option(BEAGLE_CREATE_RPM "Do you want to create a RPM package for Open BEAGLE (rpmbuild needed)?" OFF)
endif(APPLE)

# Define whether we build static or shared libs
if(NOT DEFINED LIBRARY_TYPE)
	message(STATUS "Building static library (default)")
	option(BUILD_STATIC_LIB "Build a static library?" ON)
elseif(LIBRARY_TYPE MATCHES "shared")
	message(STATUS "Building a shared library")
	option(BUILD_STATIC_LIB "Build a static library?" OFF)
else(NOT DEFINED LIBRARY_TYPE)
	message(STATUS "Building a static library (default)")
	option(BUILD_STATIC_LIB "Build a static library?" ON)
endif(NOT DEFINED LIBRARY_TYPE)
if(BUILD_STATIC_LIB)
	set(BEAGLE_LIBRARY_TYPE "STATIC")
else(BUILD_STATIC_LIB)
	set(BEAGLE_LIBRARY_TYPE "SHARED")
endif(BUILD_STATIC_LIB)

# C++0x new headers option
if(NOT DEFINED BEAGLE_USE_C0x)
	option(BEAGLE_USE_C0x "Use C++0x new headers?" OFF)
endif(NOT DEFINED BEAGLE_USE_C0x)

# Build examples option
if(NOT DEFINED BEAGLE_BUILD_EXAMPLES)
	option(BEAGLE_BUILD_EXAMPLES "Build Open BEAGLE examples?" ON)
endif(NOT DEFINED BEAGLE_BUILD_EXAMPLES)

message(STATUS "Include CMake macros...")

# Files to include for testing
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckLibraryExists)
include(CheckCXXCompilerFlag)

# Others macros to include
include(CMakeMacros/PerformTest.cmake)
include(CMakeMacros/AllFilesInOne.cmake)
include(CMakeMacros/MoveConfigFiles.cmake)

message(STATUS "Begin configuration tests...")

# Check for some headers
check_include_files(inttypes.h BEAGLE_HAVE_INTTYPES_H)
check_include_files(stdint.h   BEAGLE_HAVE_STDINT_H)
check_include_files(stdlib.h   BEAGLE_HAVE_STDLIB_H)
check_include_files(unistd.h   BEAGLE_HAVE_UNISTD_H)

# Check for /dev/urandom
if(EXISTS /dev/urandom)
	message(STATUS "/dev/urandom found")
	set(BEAGLE_HAVE_DEV_URANDOM 1)
endif(EXISTS /dev/urandom)

# Directory and extension used to find test files
if(NOT DEFINED CMAKE_DIR_TEST)
	set(CMAKE_DIR_TEST CMakeTestCode)
endif(NOT DEFINED CMAKE_DIR_TEST)
if(NOT DEFINED CMAKE_TEST_SUFFIX)
	set(CMAKE_TEST_SUFFIX ".cmake.cpp")
endif(NOT DEFINED CMAKE_TEST_SUFFIX)

# Check for built-in bool type
PerformTest(CXX_HAVE_BOOL)
if(CXX_HAVE_BOOL)
	message(STATUS "Chas built-in bool type")
	set(BEAGLE_HAVE_BOOL 1)
endif(CXX_HAVE_BOOL)

# Check for built-in long long type
PerformTest(CXX_HAVE_LONG_LONG)
if(CXX_HAVE_LONG_LONG)
	message(STATUS "Chas built-in long long type")
	set(BEAGLE_HAVE_LONG_LONG 1)
endif(CXX_HAVE_LONG_LONG)

# Check for templates
PerformTest(CXX_HAVE_TEMPLATES)
if(CXX_HAVE_TEMPLATES)
	message(STATUS "Csupports templates")
else(CXX_HAVE_TEMPLATES)
	message(SEND_ERROR "!! Sorry, templates support needed")
endif(CXX_HAVE_TEMPLATES)

# Check for built-in template scoped argument matching
PerformTest(CXX_HAVE_TEMPLATE_SCOPED_ARGUMENT_MATCHING)
if(CXX_HAVE_TEMPLATE_SCOPED_ARGUMENT_MATCHING)
	message(STATUS "Csupports template scoped argument matching")
else(CXX_HAVE_TEMPLATE_SCOPED_ARGUMENT_MATCHING)
	message(SEND_ERROR "!! Sorry, template scoped argument matching support needed")
endif(CXX_HAVE_TEMPLATE_SCOPED_ARGUMENT_MATCHING)

# Check for default template parameters
PerformTest(CXX_HAVE_DEFAULT_TEMPLATE_PARAMETERS)
if(CXX_HAVE_DEFAULT_TEMPLATE_PARAMETERS)
	message(STATUS "Csupports default template parameters")
else(CXX_HAVE_DEFAULT_TEMPLATE_PARAMETERS)
	message(SEND_ERROR "!! Sorry, default template parameters support needed")
endif(CXX_HAVE_DEFAULT_TEMPLATE_PARAMETERS)

# Check for typename
PerformTest(CXX_HAVE_TYPENAME)
if(CXX_HAVE_TYPENAME)
	message(STATUS "Chas typename qualifier")
else(CXX_HAVE_TYPENAME)
	message(SEND_ERROR "!! Sorry, typename qualifier needed")
endif(CXX_HAVE_TYPENAME)

# Check for built-in exception handling
PerformTest(CXX_HAVE_EXCEPTIONS)
if(CXX_HAVE_EXCEPTIONS)
	message(STATUS "Csupports exception handling")
else(CXX_HAVE_EXCEPTIONS)
	message(SEND_ERROR "!! Sorry, support for exception handling needed")
endif(CXX_HAVE_EXCEPTIONS)

# Check for namespaces support
PerformTest(CXX_HAVE_NAMESPACES)
if(CXX_HAVE_NAMESPACES)
	message(STATUS "Csupports namespaces")
else(CXX_HAVE_NAMESPACES)
	message(SEND_ERROR "!! Sorry, namespaces support needed")
endif(CXX_HAVE_NAMESPACES)

# Check for hash_map Ctemplate
PerformTest(HASHMAP_STD)
PerformTest(HASHMAP_GNUCXX)
PerformTest(HASHMAP_STDEXT)
if(HASHMAP_STD)
	message(STATUS "std::hash_map found")
	set(BEAGLE_HAVE_STD_HASHMAP 1)
endif(HASHMAP_STD)
if(HASHMAP_GNUCXX)
	message(STATUS "__gnu_cxx::hash_map found")
	set(BEAGLE_HAVE_GNUCXX_HASHMAP false)
	message(STATUS "__gnu_cxx::hash_map will not be enabled since some segfault occurs while using it.")
	option(BEAGLE_HAVE_GNUCXX_HASHMAP "Enable __gnu_cxx::hash_map anyway?" OFF)
endif(HASHMAP_GNUCXX)
if(HASHMAP_STDEXT)
	message(STATUS "stdext::hash_map found")
	set(BEAGLE_HAVE_STDEXT_HASHMAP 1)
endif(HASHMAP_STDEXT)
if(NOT DEFINED HASHMAP_STD AND NOT DEFINED HASHMAP_GNUCXX AND NOT DEFINED HASHMAP_STDEXT)
	message(STATUS "no hash_map found")
endif(NOT DEFINED HASHMAP_STD AND NOT DEFINED HASHMAP_GNUCXX AND NOT DEFINED HASHMAP_STDEXT)

# Check for hash_set Ctemplate
PerformTest(HASHSET_STD)
PerformTest(HASHSET_GNUCXX)
PerformTest(HASHSET_STDEXT)
if(HASHSET_STD)
	message(STATUS "std::hash_set found")
	set(BEAGLE_HAVE_STD_HASHSET 1)
endif(HASHSET_STD)
if(HASHSET_GNUCXX)
	message(STATUS "__gnu_cxx::hash_set found")
	set(BEAGLE_HAVE_GNUCXX_HASHSET false)
	message(STATUS "__gnu_cxx::hash_set will not be enabled since some segfault occurs while using it.")
	option(BEAGLE_HAVE_GNUCXX_HASHSET "Enable __gnu_cxx::hash_set anyway?" OFF)
endif(HASHSET_GNUCXX)
if(HASHSET_STDEXT)
	message(STATUS "stdext::hash_set found")
	set(BEAGLE_HAVE_STDEXT_HASHSET 1)
endif(HASHSET_STDEXT)
if(NOT DEFINED HASHSET_STD AND NOT DEFINED HASHSET_GNUCXX AND NOT DEFINED HASHSET_STDEXT)
	message(STATUS "no hash_set found")
endif(NOT DEFINED HASHSET_STD AND NOT DEFINED HASHSET_GNUCXX AND NOT DEFINED HASHSET_STDEXT)

# Check for C++0x new hash headers on GCC
if(BEAGLE_USE_C0x)
	check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_C0X)
	if(COMPILER_SUPPORTS_C0X)
		set(CMAKE_REQUIRED_FLAGS "-std=c++0x")
	endif(COMPILER_SUPPORTS_C0X)
endif(BEAGLE_USE_C0x)
PerformTest(CXX_HAVE_UNORDERED_MAP)
PerformTest(CXX_HAVE_UNORDERED_SET)
if(CXX_HAVE_UNORDERED_MAP AND CXX_HAVE_UNORDERED_SET)
	message(STATUS "compiler supports C++0x hash tables")
	set(BEAGLE_HAVE_UNORDERED_MAP true)
	set(BEAGLE_HAVE_UNORDERED_SET true)
endif(CXX_HAVE_UNORDERED_MAP AND CXX_HAVE_UNORDERED_SET)
PerformTest(CXX_HAVE_UNORDERED_MAP_TR1)
PerformTest(CXX_HAVE_UNORDERED_SET_TR1)
if(CXX_HAVE_UNORDERED_MAP_TR1)
	message(STATUS "found std::tr1::unordered_map")
	set(BEAGLE_HAVE_STDTR1_UNORDEREDMAP true)
endif(CXX_HAVE_UNORDERED_MAP_TR1)
if(CXX_HAVE_UNORDERED_SET_TR1)
	message(STATUS "found std::tr1::unordered_set")
	set(BEAGLE_HAVE_STDTR1_UNORDEREDSET true)
endif(CXX_HAVE_UNORDERED_SET_TR1)

# Check for const_cast
PerformTest(CXX_HAVE_CONST_CAST)
if(CXX_HAVE_CONST_CAST)
	message(STATUS "compiler supports const_cast<>")
	set(BEAGLE_HAVE_CONST_CAST 1)
else(CXX_HAVE_CONST_CAST)
	message(STATUS "const_cast<> not supported")
endif(CXX_HAVE_CONST_CAST)

# Check for dynamic_cast
PerformTest(CXX_HAVE_DYN_CAST)
if(CXX_HAVE_DYN_CAST)
	message(STATUS "compiler supports dynamic_cast<>")
	set(BEAGLE_HAVE_DYNAMIC_CAST 1)
else(CXX_HAVE_DYN_CAST)
	message(STATUS "dynamic_cast<> not supported")
endif(CXX_HAVE_DYN_CAST)

# Check for static_cast
PerformTest(CXX_HAVE_STATIC_CAST)
if(CXX_HAVE_STATIC_CAST)
	message(STATUS "compiler supports static_cast<>")
	set(BEAGLE_HAVE_STATIC_CAST 1)
else(CXX_HAVE_STATIC_CAST)
	message(STATUS "static_cast<> not supported")
endif(CXX_HAVE_STATIC_CAST)

# Check for reinterpret_cast
PerformTest(CXX_HAVE_REINTERPRET_CAST)
if(CXX_HAVE_REINTERPRET_CAST)
	message(STATUS "compiler supports reinterpret_cast<>")
	set(BEAGLE_HAVE_REINTERPRET_CAST 1)
else(CXX_HAVE_REINTERPRET_CAST)
	message(STATUS "reinterpret_cast<> not supported")
endif(CXX_HAVE_REINTERPRET_CAST)

# Check for isfinite
PerformTest(CXX_HAVE_ISFINITE)
if(CXX_HAVE_ISFINITE)
	message(STATUS "compiler supports isfinite()")
	set(BEAGLE_HAVE_ISFINITE 1)
else(CXX_HAVE_ISFINITE)
	message(STATUS "isfinite() not supported by the compiler")
endif(CXX_HAVE_ISFINITE)

# Check for numeric limits
PerformTest(CXX_HAVE_NUMERIC_LIMITS)
if(CXX_HAVE_NUMERIC_LIMITS)
	message(STATUS "compiler defines numeric limits")
	set(BEAGLE_HAVE_NUMERIC_LIMITS 1)
else(CXX_HAVE_NUMERIC_LIMITS)
	message(STATUS "compiler does not define numeric limits")
endif(CXX_HAVE_NUMERIC_LIMITS)

# Check for Run-time Type Identification
PerformTest(CXX_HAVE_RTTI)
if(CXX_HAVE_RTTI)
	message(STATUS "compiler supports Run-Time Type Identification")
	set(BEAGLE_HAVE_RTTI 1)
else(CXX_HAVE_RTTI)
	message(STATUS "Run-Time Type Identification not supported")
endif(CXX_HAVE_RTTI)

# Check for stringstream support
PerformTest(CXX_HAVE_SSTREAM)
if(CXX_HAVE_SSTREAM)
	message(STATUS "compiler has stringstream")
	set(BEAGLE_HAVE_SSTREAM 1)
else(CXX_HAVE_SSTREAM)
	message(SEND_ERROR "!! Sorry, no sstream found. If you are using gcc less or equal to 2.95.2, see http://gcc.gnu.org/faq.html#2.95sstream to patch your compiler")
endif(CXX_HAVE_SSTREAM)

# Define build mode
if(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
	message(STATUS "Building in release mode (default)...")
	set(CMAKE_BUILD_TYPE "RELEASE")
    set(BEAGLE_NDEBUG true)
else(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
    string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE)
	if(CMAKE_BUILD_TYPE STREQUAL "DEBUG")
		message(STATUS "Building in debug mode...")
		set(BEAGLE_NDEBUG false)
	elseif(NOT CMAKE_BUILD_TYPE STREQUAL "MINSIZEREL" AND NOT CMAKE_BUILD_TYPE STREQUAL "RELEASE" AND NOT CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
		message(STATUS "## Warning: unhandled build mode ${CMAKE_BUILD_TYPE}, will build in release mode")
		set(CMAKE_BUILD_TYPE "RELEASE" FORCE)
		set(BEAGLE_NDEBUG true)
	else(CMAKE_BUILD_TYPE STREQUAL "DEBUG")				
		set(BEAGLE_NDEBUG true)
	endif(CMAKE_BUILD_TYPE STREQUAL "DEBUG")
endif(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")

set(BEAGLE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")

# Fast compilation option
if(NOT DEFINED CMAKE_FAST_COMPILATION)
	option(CMAKE_FAST_COMPILATION "Do you want to active fast compilation mode?" OFF)
endif(NOT DEFINED CMAKE_FAST_COMPILATION)

# Check for PACC
find_package(PACC)

# Check for zlib
find_package(ZLIB)
if(ZLIB_FOUND)
    include_directories(${ZLIB_INCLUDE_DIR})
	install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/gzstream.h DESTINATION include)
	set(BEAGLE_HAVE_LIBZ 1)
else(ZLIB_FOUND)
    message(STATUS "Cannot find the zlib library") 
endif(ZLIB_FOUND)

# Allow to disable all annoying Visual Cwarnings
if(MSVC)
	option(BEAGLE_MSVC_NOWARNINGS "Disable MS Visual Studio compilation warnings?" ON)
endif(MSVC)
if(BEAGLE_MSVC_NOWARNINGS)
	message(STATUS "MS Visual Studio compilation warnings disabled")
	add_definitions(/w)
endif(BEAGLE_MSVC_NOWARNINGS)

# Use the fixed FindMPI modified to work under OS X
find_package(MPI)
if(MPI_FOUND)
	message(STATUS "MPI found")
	set(BEAGLE_HAVE_MPI 1)
	if(NOT DEFINED BEAGLE_NO_HPC)
		include_directories("${MPI_INCLUDE_PATH}")
		find_program(MPI_INFO NAMES ompi_info)
		mark_as_advanced(MPI_INFO)
		if(MPI_INFO)
			exec_program(${MPI_INFO} OUTPUT_VARIABLE MPI_INFO_LIST)
			string(REGEX MATCHALL "exceptions: yes" MPI_EXCEPTIONS "${MPI_INFO_LIST}")
			string(REGEX MATCHALL "mpi: yes, progress: (yes|no)" MPI_THREADS "${MPI_INFO_LIST}")
			if(NOT MPI_EXCEPTIONS)
				message(STATUS "!! The current MPI installed version doesn't support Cexceptions. HPC won't be compiled.")
				option(BEAGLE_NO_HPC "Disable Open Beagle HPC?" ON)
			endif(NOT MPI_EXCEPTIONS)
			if(NOT MPI_THREADS)
				message(STATUS "!! The current MPI installed version doesn't support Cmulti-threads. HPC won't be compiled.")
				option(BEAGLE_NO_HPC "Disable Open Beagle HPC?" ON)
			endif(NOT MPI_THREADS)
		endif(MPI_INFO)
		if(MPI_THREADS AND MPI_EXCEPTIONS)
			option(BEAGLE_NO_HPC "Disable Open Beagle HPC?" OFF)
		endif(MPI_THREADS AND MPI_EXCEPTIONS)
	
	endif(NOT DEFINED BEAGLE_NO_HPC)
else(MPI_FOUND)
	message(STATUS "MPI not found")
	message(STATUS "!! Open BEAGLE HPC relies on MPI, and thus will not be enabled.")
	option(BEAGLE_NO_HPC "Disable Open BEAGLE HPC?" ON)
endif(MPI_FOUND)

# Check for OpenMP
# BEAGLE_OMP_MODE = DYNAMIC | STATIC | NONE (default = NONE)
# FindOpenMP macro is not available in all configurations, so we try to use the "official" package
find_package(OpenMP QUIET)
mark_as_advanced(OpenMP_DIR)
# If CMake fails to locate FindOpenMP, we use our own macro
if(OpenMP_DIR MATCHES OpenMP_DIR-NOTFOUND)
	include(CMakeMacros/FindOpenMP.cmake)
endif(OpenMP_DIR MATCHES OpenMP_DIR-NOTFOUND)

if(OPENMP_FOUND)
	message(STATUS "OpenMP found")
	
	if(NOT DEFINED BEAGLE_OMP_MODE)
		message(STATUS "If you want to enable OpenMP, set BEAGLE_OMP_MODE to STATIC or DYNAMIC, depending in which mode scheduler should work.")
		set(BEAGLE_OMP_MODE "NONE" CACHE STRING "OpenMP scheduler modes : NONE (do not use OpenMP at all), STATIC (reproducible results), DYNAMIC (non-reproducible results)")
	endif(NOT DEFINED BEAGLE_OMP_MODE)

	string(TOUPPER ${BEAGLE_OMP_MODE} BEAGLE_OMP_MODE)

	if(BEAGLE_OMP_MODE MATCHES "NONE")
		message(STATUS "OpenMP is not enabled, set BEAGLE_OMP_MODE to STATIC | DYNAMIC to enable it.")
		set(BEAGLE_USE_OMP_R False)
		set(BEAGLE_USE_OMP_NR False)
	elseif(BEAGLE_OMP_MODE MATCHES "STATIC")
		message(STATUS "OpenMP enabled, scheduler set to static mode.")
		set(BEAGLE_USE_OMP_R True)
		set(BEAGLE_USE_OMP_NR False)
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
	elseif(BEAGLE_OMP_MODE MATCHES "DYNAMIC")
		message(STATUS "OpenMP enabled, scheduler set to dynamic mode.")
		set(BEAGLE_USE_OMP_NR True)
		set(BEAGLE_USE_OMP_R False)
		set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
	else(BEAGLE_OMP_MODE MATCHES "NONE")
		message(STATUS "Invalid value for BEAGLE_OMP_MODE : NONE | STATIC | DYNAMIC expected, but found ${BEAGLE_OMP_MODE}; OpenMP is disabled.")
		set(BEAGLE_OMP_MODE "NONE" CACHE STRING "OpenMP scheduler modes : NONE (do not use OpenMP at all), STATIC (reproducible results), DYNAMIC (non-reproducible results)")
		set(BEAGLE_USE_OMP_R False)
		set(BEAGLE_USE_OMP_NR False)
	endif(BEAGLE_OMP_MODE MATCHES "NONE")
	
	if(NOT BEAGLE_OMP_MODE MATCHES "NONE")
		set(BEAGLE_HAVE_OPENMP 1)
		
		if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
			message(STATUS "Compiling with GNU, parallel version of STL algorithms will be used if they are available.")
			execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CMAKE_CXX_COMPILER_VERSION)
			
			if(CMAKE_CXX_COMPILER_VERSION MATCHES "4?\\.[3-9]?\\.[0-9]")
				message(STATUS "GCC ${CMAKE_CXX_COMPILER_VERSION} found, enabling parallel STL")

				set(CMAKE_REQUIRED_FLAGS "-L${PACC_LIB_FOUND_DIR} -I${PACC_INCLUDE_FOUND_DIR} -lpacc -fopenmp -D_GLIBCXX_PARALLEL")
				message(STATUS "Check if PACC has been compiled with parallel STL...")
				PerformTest(PACC_HAVE_PARALLEL_STL)
				if(NOT PACC_HAVE_PARALLEL_STL)
					message("!! Warning : your PACC library has not been compiled with parallel version of STL, forced to disable parallel STL for beagle too...")
				else(NOT PACC_HAVE_PARALLEL_STL)
					message(STATUS "PACC parallel STL ok...")
					add_definitions(-D_GLIBCXX_PARALLEL)
				endif(NOT PACC_HAVE_PARALLEL_STL)
				set(CMAKE_REQUIRED_FLAGS)		# Unset modified CMake variables
			else(CMAKE_CXX_COMPILER_VERSION MATCHES "4?\\.[3-9]?\\.[0-9]")
				message(STATUS "Parallel STL requires GCC >= 4.3, you are using ${CMAKE_CXX_COMPILER_VERSION}")
			endif(CMAKE_CXX_COMPILER_VERSION MATCHES "4?\\.[3-9]?\\.[0-9]")			
		endif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
	endif(NOT BEAGLE_OMP_MODE MATCHES "NONE")

	mark_as_advanced(BEAGLE_USE_OMP_R BEAGLE_USE_OMP_NR)

else(OPENMP_FOUND)
	message(STATUS "OpenMP not found")
endif(OPENMP_FOUND)

# Look for threads libraries
message(STATUS "++ Looking for threads libraries...")
include(FindThreads)
if(CMAKE_USE_WIN32_THREADS_INIT)
	# Windows environment
	message(STATUS "++ Using Windows threads..."  ${CMAKE_THREAD_LIBS_INIT})
	set(PACC_THREADS_WIN32 true)
elseif(CMAKE_USE_PTHREADS_INIT OR CMAKE_HP_PTHREADS_INIT)
	# POSIX environment
	message(STATUS "++ Using POSIX threads..." ${CMAKE_THREAD_LIBS_INIT})
	set(PACC_THREADS_POSIX true)
else(CMAKE_USE_WIN32_THREADS_INIT)
	# Non-supported environment
    message(SEND_ERROR "## Cannot find any thread library!")
endif(CMAKE_USE_WIN32_THREADS_INIT)

# Generate Beagle/config.hpp file
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/config.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/include/Beagle/config.hpp")

# Glob src
file(GLOB BEAGLE_CORE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/*.cpp")
file(GLOB BEAGLE_EC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC/*.cpp")
file(GLOB BEAGLE_BITSTR_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr/*.cpp")
file(GLOB BEAGLE_FLTVEC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/*.cpp")
file(GLOB BEAGLE_INTVEC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/IntVec/*.cpp")
file(GLOB BEAGLE_ES_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES/*.cpp")
file(GLOB BEAGLE_SAES_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/SAES/*.cpp")

# Glob headers
file(GLOB BEAGLE_CORE_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/*.hpp")
file(GLOB BEAGLE_EC_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC/*.hpp")
file(GLOB BEAGLE_BITSTR_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr/*.hpp")
file(GLOB BEAGLE_FLTVEC_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/*.hpp")
file(GLOB BEAGLE_INTVEC_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/IntVec/*.hpp")
file(GLOB BEAGLE_ES_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES/*.hpp")
file(GLOB BEAGLE_SAES_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/SAES/*.hpp")

# Remove OpenMP files if OpenMP it no used
if(NOT BEAGLE_USE_OMP_NR AND NOT BEAGLE_USE_OMP_R)
    list(REMOVE_ITEM BEAGLE_CORE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/OpenMP.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/RandomizerMulti.cpp")
    list(REMOVE_ITEM BEAGLE_CORE_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/OpenMP.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/RandomizerMulti.hpp")
endif(NOT BEAGLE_USE_OMP_NR AND NOT BEAGLE_USE_OMP_R)

# Fast compilation switch
if(CMAKE_FAST_COMPILATION)
	message(STATUS "Using fast compilation mode...")
	AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/libBeagle-Core.cpp" ${BEAGLE_CORE_SRC})
	set(BEAGLE_CORE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/libBeagle-Core.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC/libBeagle-EC.cpp" ${BEAGLE_EC_SRC})
    set(BEAGLE_EC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC/libBeagle-EC.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr/libBeagle-BitStr.cpp" ${BEAGLE_BITSTR_SRC})
    set(BEAGLE_BITSTR_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr/libBeagle-BitStr.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-FltVec.cpp" ${BEAGLE_FLTVEC_SRC})
    set(BEAGLE_FLTVEC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-FltVec.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/IntVec/libBeagle-IntVec.cpp" ${BEAGLE_INTVEC_SRC})
    set(BEAGLE_INTVEC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/IntVec/libBeagle-IntVec.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES/libBeagle-ES.cpp" ${BEAGLE_ES_SRC})
    set(BEAGLE_ES_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES/libBeagle-ES.cpp")
    AllFilesInOne("${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES/libBeagle-SAES.cpp" ${BEAGLE_SAES_SRC})
    set(BEAGLE_SAES_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/SAES/libBeagle-SAES.cpp")
	message(STATUS "Include files generated...")
else(CMAKE_FAST_COMPILATION)
	message(STATUS "Using normal compilation mode...")
	file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core/libBeagle-Core.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC/libBeagle-EC.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr/libBeagle-BitStr.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-FltVec.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-IntVec.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-ES.cpp")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec/libBeagle-SAES.cpp")
endif(CMAKE_FAST_COMPILATION)

# Include headers required
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_BINARY_DIR}/include")

# Create Beagle-Core library target
add_library(Beagle-Core ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_CORE_SRC})
target_link_libraries(Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-Core ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
# Do we want to use C++0x?
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-Core PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-Core PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-Core PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_CORE_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/beagle" false)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Beagle/config.hpp DESTINATION include/Beagle)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/Core.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_CORE_HEADERS} DESTINATION include/Beagle/Core)
install(TARGETS Beagle-Core DESTINATION lib)

# Create Beagle-EC library target
add_library(Beagle-EC ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_EC_SRC})
target_link_libraries(Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-EC ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-EC PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-EC PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-EC PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_EC_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/EC" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/EC.hpp DESTINATION "${BEAGLE_OUTPUT_DIR}/include/Beagle")
install(FILES ${BEAGLE_EC_HEADERS} DESTINATION "${BEAGLE_OUTPUT_DIR}/include/Beagle/EC")
install(TARGETS Beagle-EC DESTINATION "${BEAGLE_OUTPUT_DIR}/lib")

# Create Beagle-BitStr library target
add_library(Beagle-BitStr ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_BITSTR_SRC})
target_link_libraries(Beagle-BitStr Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-BitStr ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-BitStr PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-BitStr PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-BitStr PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_BITSTR_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/BitStr" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/BitStr.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_BITSTR_HEADERS} DESTINATION include/Beagle/BitStr)
install(TARGETS Beagle-BitStr DESTINATION lib)

# Create Beagle-FltVec library target
add_library(Beagle-FltVec ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_INTVEC_SRC})
target_link_libraries(Beagle-FltVec Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-FltVec ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-FltVec PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-FltVec PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-FltVec PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_INTVEC_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/FltVec" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/FltVec.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_INTVEC_HEADERS} DESTINATION include/Beagle/FltVec)
install(TARGETS Beagle-FltVec DESTINATION lib)

# Create Beagle-IntVec library target
add_library(Beagle-IntVec ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_INTVEC_SRC})
target_link_libraries(Beagle-IntVec Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-IntVec ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-IntVec PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-IntVec PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-IntVec PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_INTVEC_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/IntVec" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/IntVec.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_INTVEC_HEADERS} DESTINATION include/Beagle/IntVec)
install(TARGETS Beagle-IntVec DESTINATION lib)

# Create Beagle-ES library target
add_library(Beagle-ES ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_ES_SRC})
target_link_libraries(Beagle-ES Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-ES ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-ES PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-ES PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-ES PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_FLTVEC_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/ES" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/ES.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_FLTVEC_HEADERS} DESTINATION include/Beagle/FltVec)
install(TARGETS Beagle-FltVec DESTINATION lib)

# Create Beagle-SAES library target
add_library(Beagle-SAES ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_SAES_SRC})
target_link_libraries(Beagle-SAES Beagle-EC Beagle-Core pacc)
if(ZLIB_FOUND)
    target_link_libraries(Beagle-SAES ${ZLIB_LIBRARY})
endif(ZLIB_FOUND)
if(BUILD_STATIC_LIB)
    set_target_properties(Beagle-SAES PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
else(BUILD_STATIC_LIB)
    set_target_properties(Beagle-SAES PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
endif(BUILD_STATIC_LIB)
if(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
    set_target_properties(Beagle-SAES PROPERTIES COMPILE_FLAGS "-std=c++0x")
endif(COMPILER_SUPPORTS_C0X AND BEAGLE_USE_C0x)
MoveConfigFiles("${BEAGLE_SAES_HEADERS}" "${BEAGLE_OUTPUT_DIR}/include/Beagle/SAES" false)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/Beagle/SAES.hpp DESTINATION include/Beagle)
install(FILES ${BEAGLE_SAES_HEADERS} DESTINATION include/Beagle/SAES)
install(TARGETS Beagle-SAES DESTINATION lib)

# Create Beagle-HPC library target
#if(NOT BEAGLE_NO_HPC)
#    if(MPI_FOUND)
#		if(CMAKE_FAST_COMPILATION)
#			add_library(Beagle-HPC ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_HPC_SRC} ${MPI_INCLUDE_PATH})
#		else(CMAKE_FAST_COMPILATION)
#			add_library(Beagle-HPC ${BEAGLE_LIBRARY_TYPE} ${BEAGLE_HPC_SRC} ${BEAGLE_HPC_HEADERS})
#		endif(CMAKE_FAST_COMPILATION)
#		add_dependencies(Beagle-HPC Beagle)
#		set_target_properties(Beagle-HPC PROPERTIES LINK_FLAGS ${MPI_LINK_FLAGS})
#		target_link_libraries(Beagle-HPC Beagle ${MPI_LIBRARIES})
#		if(BUILD_STATIC_LIB)
#			set_target_properties(Beagle-HPC PROPERTIES VERSION ${BEAGLE_VERSION} ARCHIVE_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
#		else(BUILD_STATIC_LIB)
#			set_target_properties(Beagle-HPC PROPERTIES VERSION ${BEAGLE_VERSION} LIBRARY_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/lib")
#		endif(BUILD_STATIC_LIB)
#	else(MPI_FOUND)
#		message(SEND_ERROR "!! Sorry, no MPI found. Open Beagle HPC needs MPI, to compile without HPC, compile with BEAGLE_NO_HPC")	
#	endif(MPI_FOUND)
#endif(NOT BEAGLE_NO_HPC)

if(BEAGLE_BUILD_EXAMPLES)
	message(STATUS "Will build Open BEAGLE examples, you can avoid it if you want by setting BEAGLE_BUILD_EXAMPLES to false")
	# ant example
	file(GLOB ANT_SRC  examples/ant/*.cpp)
	file(GLOB ANT_DATA examples/ant/*.conf examples/ant/*.xml examples/ant/*.trail examples/ant/ReadMe.txt)
	add_executable(ant ${ANT_SRC})
	add_dependencies(ant Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(ant Beagle-GP Beagle-EC Beagle-Core pacc)
	set_target_properties(ant PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/ant")
	MoveConfigFiles("${ANT_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/ant" false)
	install(TARGETS ant DESTINATION bin/Beagle/ant)
	install(FILES ${ANT_DATA} DESTINATION bin/Beagle/ant)

	# knapsack example
	file(GLOB KNAPSACK_SRC  examples/knapsack/*.cpp)
	file(GLOB KNAPSACK_DATA examples/knapsack/*.conf examples/knapsack/ReadMe.txt)
	add_executable(knapsack ${KNAPSACK_SRC})
	add_dependencies(knapsack Beagle-EMO Beagle-BitStr Beagle-EC Beagle-Core)
	target_link_libraries(knapsack Beagle-EMO Beagle-BitStr Beagle-EC Beagle-Core pacc)
	set_target_properties(knapsack PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/knapsack")
	MoveConfigFiles("${KNAPSACK_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/knapsack" false)
	install(TARGETS knapsack DESTINATION bin/Beagle/knapsack)
	install(FILES ${KNAPSACK_DATA} DESTINATION bin/Beagle/knapsack)

	# knapsack-hpc example
	if(NOT BEAGLE_NO_HPC)
		file(GLOB KNAPSACK_HPC_SRC  examples/knapsack-hpc/*.cpp)
		file(GLOB KNAPSACK_HPC_DATA examples/knapsack-hpc/*.conf)
		add_executable(knapsack-hpc ${KNAPSACK_HPC_SRC})
		add_dependencies(knapsack-hpc Beagle-HPC Beagle-EMO Beagle-BitStr Beagle-EC Beagle-Core)
		target_link_libraries(knapsack-hpc Beagle-HPC Beagle-EMO Beagle-BitStr Beagle-EC Beagle-Core pacc)
		set_target_properties(knapsack-hpc PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/knapsack-hpc")
		MoveConfigFiles("${KNAPSACK_HPC_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/knapsack-hpc" false)
		install(TARGETS knapsack-hpc DESTINATION bin/Beagle/knapsack-hpc)
		install(FILES ${KNAPSACK_HPC_DATA} DESTINATION bin/Beagle/knapsack-hpc)
	endif(NOT BEAGLE_NO_HPC)

	# maxfct example
	file(GLOB MAXFCT_SRC  examples/maxfct/*.cpp)
	file(GLOB MAXFCT_DATA examples/maxfct/*.conf examples/maxfct/ReadMe.txt)
	add_executable(maxfct ${MAXFCT_SRC})
	add_dependencies(maxfct Beagle-BitStr Beagle-EC Beagle-Core)
	target_link_libraries(maxfct Beagle-BitStr Beagle-EC Beagle-Core pacc)
	set_target_properties(maxfct PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/maxfct")
	MoveConfigFiles("${MAXFCT_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/maxfct" false)
	install(TARGETS maxfct DESTINATION bin/Beagle/maxfct)
	install(FILES ${MAXFCT_DATA} DESTINATION bin/Beagle/maxfct)

	# maxfctes example
	file(GLOB MAXFCTES_SRC  examples/maxfctes/*.cpp)
	file(GLOB MAXFCTES_DATA examples/maxfctes/*.conf examples/maxfctes/ReadMe.txt)
	add_executable(maxfctes ${MAXFCTES_SRC})
	add_dependencies(maxfctes Beagle-ES Beagle-EC Beagle-Core)
	target_link_libraries(maxfctes Beagle-ES Beagle-EC Beagle-Core pacc)
	set_target_properties(maxfctes PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/maxfctes")
	MoveConfigFiles("${MAXFCTES_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/maxfctes" false)
	install(TARGETS maxfctes DESTINATION bin/Beagle/maxfctes)
	install(FILES ${MAXFCTES_DATA} DESTINATION bin/Beagle/maxfctes)

	# maxfctfloat example
	file(GLOB MAXFCTFLOAT_SRC  examples/maxfctfloat/*.cpp)
	file(GLOB MAXFCTFLOAT_DATA examples/maxfctfloat/*.conf examples/maxfctfloat/ReadMe.txt)
	add_executable(maxfctfloat ${MAXFCTFLOAT_SRC})
	add_dependencies(maxfctfloat Beagle-FltVec Beagle-EC Beagle-Core)
	target_link_libraries(maxfctfloat Beagle-FltVec Beagle-EC Beagle-Core pacc)
	set_target_properties(maxfctfloat PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/maxfctfloat")
	MoveConfigFiles("${MAXFCTFLOAT_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/maxfctfloat" false)
	install(TARGETS maxfctfloat DESTINATION bin/Beagle/maxfctfloat)
	install(FILES ${MAXFCTFLOAT_DATA} DESTINATION bin/Beagle/maxfctfloat)

	# multiplexer example
	file(GLOB MULTIPLEXER_SRC  examples/multiplexer/*.cpp)
	file(GLOB MULTIPLEXER_DATA examples/multiplexer/*.conf examples/multiplexer/ReadMe.txt)
	add_executable(multiplexer ${MULTIPLEXER_SRC})
	add_dependencies(multiplexer Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(multiplexer Beagle-GP Beagle-EC Beagle pacc)
	set_target_properties(multiplexer PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/multiplexer")
	MoveConfigFiles("${MULTIPLEXER_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/multiplexer" false)
	install(TARGETS multiplexer DESTINATION bin/Beagle/multiplexer)
	install(FILES ${MULTIPLEXER_DATA} DESTINATION bin/Beagle/multiplexer)

	# onemax example
	file(GLOB ONEMAX_SRC  examples/onemax/*.cpp)
	file(GLOB ONEMAX_DATA examples/onemax/*.conf examples/onemax/ReadMe.txt)
	add_executable(onemax ${ONEMAX_SRC})
	add_dependencies(onemax Beagle-BitStr Beagle-EC Beagle-Core)
	target_link_libraries(onemax Beagle-BitStr Beagle-EC Beagle-Core pacc)
	set_target_properties(onemax PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/onemax")
	MoveConfigFiles("${ONEMAX_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/onemax" false)
	install(TARGETS onemax DESTINATION bin/Beagle/onemax)
	install(FILES ${ONEMAX_DATA} DESTINATION bin/Beagle/onemax)

	# parity example
	set(PARITY_SRC examples/parity/ParityEvalOp.cpp examples/parity/ParityMain.cpp)
	set(PARITY_FAST_SRC examples/parity/ParityFastEvalOp.cpp examples/parity/ParityFastMain.cpp)
	file(GLOB PARITY_DATA examples/parity/*.conf examples/parity/ReadMe.txt)
	add_executable(parity ${PARITY_SRC})
	add_dependencies(parity Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(parity Beagle-GP Beagle-EC Beagle-Core pacc)
	add_executable(parity-fast ${PARITY_FAST_SRC})
	add_dependencies(parity-fast Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(parity-fast Beagle-GP Beagle-EC Beagle-Core pacc)
	set_target_properties(parity parity-fast PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/parity")
	MoveConfigFiles("${PARITY_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/parity" false)
	install(TARGETS parity parity-fast DESTINATION bin/Beagle/parity)
	install(FILES ${PARITY_DATA} DESTINATION bin/Beagle/parity)

	# spambase example
	file(GLOB SPAMBASE_SRC  examples/spambase/*.cpp)
	file(GLOB SPAMBASE_DATA examples/spambase/*.conf examples/spambase/spambase.data examples/spambase/ReadMe.txt)
	add_executable(spambase ${SPAMBASE_SRC})
	add_dependencies(spambase Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(spambase Beagle-GP Beagle-EC Beagle-Core pacc)
	set_target_properties(spambase PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/spambase")
	MoveConfigFiles("${SPAMBASE_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/spambase" false)
	install(TARGETS spambase DESTINATION bin/Beagle/spambase)
	install(FILES ${SPAMBASE_DATA} DESTINATION bin/Beagle/spambase)

	# symbreg example
	file(GLOB SYMBREG_SRC  examples/symbreg/*.cpp)
	file(GLOB SYMBREG_DATA examples/symbreg/*.conf examples/symbreg/ReadMe.txt)
	add_executable(symbreg ${SYMBREG_SRC})
	add_dependencies(symbreg Beagle-GP Beagle-EC Beagle-Core)
	target_link_libraries(symbreg Beagle-GP Beagle-EC Beagle-Core pacc)
	set_target_properties(symbreg PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/symbreg")
	MoveConfigFiles("${SYMBREG_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/symbreg" false)
	install(TARGETS symbreg DESTINATION bin/Beagle/symbreg)
	install(FILES ${SYMBREG_DATA} DESTINATION bin/Beagle/symbreg)

	# tsp example
	file(GLOB TSP_SRC  examples/tsp/*.cpp)
	file(GLOB TSP_DATA examples/tsp/*.conf examples/tsp/ReadMe.txt)
	add_executable(tsp ${TSP_SRC})
	add_dependencies(tsp Beagle-IntVec Beagle-EC Beagle-Core)
	target_link_libraries(tsp Beagle-IntVec Beagle-EC Beagle-Core pacc)
	set_target_properties(tsp PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/tsp")
	MoveConfigFiles("${TSP_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/tsp" false)
	install(TARGETS tsp DESTINATION bin/Beagle/tsp)
	install(FILES ${TSP_DATA} DESTINATION bin/Beagle/tsp)

	# tsp-hpc example
	if(NOT BEAGLE_NO_HPC)
		file(GLOB TSP_HPC_SRC  examples/tsp-hpc/*.cpp)
		file(GLOB TSP_HPC_DATA examples/tsp-hpc/*.conf)
		add_executable(tsp-hpc ${TSP_HPC_SRC})
		add_dependencies(tsp-hpc Beagle-HPC Beagle-IntVec Beagle-EC Beagle-Core)
		target_link_libraries(tsp-hpc Beagle-HPC Beagle-IntVec Beagle-EC Beagle-Core pacc)
		set_target_properties(tsp-hpc PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/tsp-hpc")
		MoveConfigFiles("${TSP_HPC_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/tsp-hpc" false)
		install(TARGETS tsp-hpc DESTINATION bin/Beagle/tsp-hpc)
		install(FILES ${TSP_DATA} DESTINATION bin/Beagle/tsp-hpc)
	endif(NOT BEAGLE_NO_HPC)

	# zeromin example
	file(GLOB ZEROMIN_SRC  examples/zeromin/*.cpp)
	file(GLOB ZEROMIN_DATA examples/zeromin/*.conf examples/zeromin/ReadMe.txt)
	add_executable(zeromin ${ZEROMIN_SRC})
	add_dependencies(zeromin Beagle-BitStr Beagle-EC Beagle-Core)
	target_link_libraries(zeromin Beagle-BitStr Beagle-EC Beagle-Core pacc)
	set_target_properties(zeromin PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BEAGLE_OUTPUT_DIR}/bin/zeromin")
	MoveConfigFiles("${ZEROMIN_DATA}" "${BEAGLE_OUTPUT_DIR}/bin/zeromin" false)
	install(TARGETS zeromin DESTINATION bin/Beagle/zeromin)
	install(FILES ${ZEROMIN_DATA} DESTINATION bin/Beagle/Beaglezeromin)

else(BEAGLE_BUILD_EXAMPLES)
	message(STATUS "Will not build examples, you can build them by rerun CMake with BEAGLE_BUILD_EXAMPLES set to true")
endif(BEAGLE_BUILD_EXAMPLES)
# BEAGLE_CREATE_DMG (needs MacOS)
# BEAGLE_CREATE_UNIX_BIN
# BEAGLE_CREATE_DEB
# BEAGLE_CREATE_RPM (need rpmbuild)
# BEAGLE_CREATE_WIN32_SETUP

# Enable package creation
set(CPACK_PACKAGE_NAME OpenBEAGLE)
set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/1-ReadMe.txt)
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/2-License.txt)
set(CPACK_PACKAGE_VERSION ${BEAGLE_VERSION})
set(CPACK_PACKAGE_CONTACT "christian.gagne@gel.ulaval.ca")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open BEAGLE: A Generic Evolutionary Computation Framework in C++")

if(BEAGLE_CREATE_DMG)
	if(NOT APPLE)
		message(SEND_ERROR "!! Cannot create PKG packages on an other system than MacOS")
	endif(NOT APPLE)
	set(CPACK_PACKAGE_FILE_NAME "Beagle-${BEAGLE_VERSION}")
endif(BEAGLE_CREATE_DMG)

if(BEAGLE_CREATE_WIN32_SETUP)
	find_program(NSIS_FOUND NSIS PATHS "C:/Program Files/NSIS") 	# Try to locate NSIS
	if(NSIS_FOUND MATCHES NSIS_FOUND-NOTFOUND)
		message(STATUS "Warning : to pack this library into a Windows Installer executable, you will need NSIS.")
		message(STATUS " NSIS is not currently installed on your system, or its path is not defined.\n You can download it at http://nsis.sourceforge.net")
	else(NSIS_FOUND MATCHES NSIS_FOUND-NOTFOUND)
		message(STATUS "NSIS installer creator found")
	endif(NSIS_FOUND MATCHES NSIS_FOUND-NOTFOUND)
	set(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenBEAGLE")
	#set(CPACK_PACKAGE_ICON "pacc_banner.bmp")
	include(InstallRequiredSystemLibraries)
	install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
endif(BEAGLE_CREATE_WIN32_SETUP)

if(BEAGLE_CREATE_UNIX_BIN)
	if(NOT UNIX)
		message(SEND_ERROR "!! Cannot create UNIX universal binaries on a non-UNIX system...")
	endif(NOT UNIX)
	set(CPACK_SOURCE_GENERATOR ${CPACK_SOURCE_GENERATOR} "TGZ" "ZIP")
endif(BEAGLE_CREATE_UNIX_BIN)

if(BEAGLE_CREATE_DEB)
	set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.4)")
	add_custom_command(TARGET zeromin POST_BUILD COMMAND cpack -G DEB -D DEBIAN_PACKAGE_ARCHITECTURE="i386")
endif(BEAGLE_CREATE_DEB)

if(BEAGLE_CREATE_RPM)
	message(STATUS "Warning : you need to have 'rpmbuild' installed in order to generate RPM files")
	set(CPACK_SOURCE_GENERATOR ${CPACK_SOURCE_GENERATOR} "RPM")
endif(BEAGLE_CREATE_RPM)

include(CPack)

